/****************************** (C) COPYRIGHT 2016 RSEStudio ****************************
* File Name          : 
* Author             : RSES_Liyang
* Version            : V1.0.0
* Date               : 00-May-18
* Description        : 
*****************************************************************************************/
/* Includes ----------------------------------------------------------------------------*/
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "Bsp.h"
#include "main.h"
#include "usbd_iProfile.h"
#include "ComModuleUSB.h"


/* Private macro -----------------------------------------------------------------------*/
/* Extern variables --------------------------------------------------------------------*/
TaskHandle_t thread_usb_com=NULL; 		/* 任务句柄 */  //struct rt_thread iprofile_thread;
StaticTask_t thread_usb_com_tcb;   	
StackType_t  Stk_usb_com[5120];		/* 任务栈空间 */

//int16_t  Ble_comm_trans_status;
//int16_t  Ble_comm_trans_length;

SemaphoreHandle_t sem_usb_com = NULL;
StaticSemaphore_t xsem_usb_com;  // 存储互斥量的数据结构

uint8_t comModule_int_Buf[32];

uint8_t usb_trans_length;
uint8_t comModule_Buf[64];

frame_head_t gCommHead;
static uint8_t CommDataBuf[64];
static int32_t (*comm_cmd_func_cb[COMM_CMD_MAX])(frame_head_t *p_cmd_head);

/* Private typedef ---------------------------------------------------------------------*/
/* Private variables -------------------------------------------------------------------*/
/* Private functions -------------------------------------------------------------------*/


void USBComModuleInit(void)
{
	uint16_t i;	
	for(i=0;i<COMM_CMD_MAX;i++)
	{
		comm_cmd_func_cb[i] = 0;
	}
}

int32_t USB_comm_command_register(uint16_t command_id,cb_command cb_func)
{
	if(command_id>COMM_CMD_MAX)
	{
		return -1;
	}
	
	comm_cmd_func_cb[command_id] = cb_func;
	return 0;
}


static int16_t RecvDataFrame(void)
{
	uint8_t ret = 0;
	uint8_t cmd_id;
	uint8_t RecvDataLength;
	uint8_t DataLen;
	uint8_t CRC8;
  uint8_t i;
	
	RecvDataLength = usb_trans_length;
	
	if((RecvDataLength>64)||(RecvDataLength<4))
	{
		ret = CMD_ERROR;
		goto frame_recv_error;
	}
	
	gCommHead.pDataBuf = CommDataBuf;
	
	gCommHead.Command = comModule_Buf[0];
	gCommHead.Proces = comModule_Buf[1];
	gCommHead.DataLength = comModule_Buf[2];
	gCommHead.DeviceStatus = comModule_Buf[3];
	DataLen = gCommHead.DataLength;
	
	if(DataLen>59)
	{
		ret = CMD_ERROR;
		goto frame_recv_error;
	}
	
	if(CRC8Software(comModule_Buf,RecvDataLength) != 0) 
	{		
		ret = CMD_ERROR;
		goto frame_recv_error;
	}
	

	{
		cmd_id = gCommHead.Command;
	
		if(cmd_id>=COMM_CMD_MAX)
		{		
			ret = CMD_UNSUPPORT;
			goto frame_recv_error;
		}
		
		if(comm_cmd_func_cb[cmd_id]==0)
		{
			ret = CMD_UNSUPPORT;
			goto frame_recv_error;
		}
		
		for(i=0;i<DataLen;i++)
		{
			gCommHead.pDataBuf[i] = comModule_Buf[4+i];
		}
		
		if(comm_cmd_func_cb[gCommHead.Command](&gCommHead) == 3)
		{
			
		}
		
		comModule_Buf[0] = gCommHead.Command;
		comModule_Buf[1] = gCommHead.Proces;
		comModule_Buf[2] = gCommHead.DataLength;
		comModule_Buf[3] = gCommHead.DeviceStatus;
		
		if(gCommHead.DataLength>59)
		{
			ret = CMD_ERROR;
			goto frame_recv_error;
		}
		
		for(i=0;i<gCommHead.DataLength;i++)
		{
			comModule_Buf[4+i] = gCommHead.pDataBuf[i];
		}
		CRC8 = CRC8Software(comModule_Buf,gCommHead.DataLength + 4);
		comModule_Buf[gCommHead.DataLength + 4] = CRC8;
		
		USB_Trans_CmdBuf(comModule_Buf,gCommHead.DataLength + 5);
		iProfile.sys_status.HostConnect=1;

		return 0;
	}
	
frame_recv_error:
		
	//comModule_Buf[0] = USB_BulkWriteBuf[0];
	//comModule_Buf[1] = USB_BulkWriteBuf[1];
	//comModule_Buf[2] = 0;
	comModule_Buf[3] = ret;
	
	CRC8 = CRC8Software(comModule_Buf,4);
	comModule_Buf[4] = CRC8;
	
	USB_Trans_CmdBuf(comModule_Buf,gCommHead.DataLength + 5);
				
	return -1;
}


void Task_usb_com(void *parameter)
{
	static BaseType_t result;
	while(1)
	{
		result = xSemaphoreTake(sem_usb_com,portMAX_DELAY);
		if(result == pdTRUE)
		{
			RecvDataFrame();
		}
	}
}


int USBCommunication_Start(void)
{
	// rt_err_t result;
	
	sem_usb_com = xSemaphoreCreateCountingStatic(10,0,&xsem_usb_com);
    if (sem_usb_com == NULL)
    {
        while(1);
    }

    usb_port_init();

	// 创建静态任务
	//任务函数、任务名称 (用于调试)、栈大小 (以StackType_t为单位)、
	//传递给任务的参数、任务优先级、静态任务控制块
    thread_usb_com = xTaskCreateStatic(
		Task_usb_com, "usb_com", sizeof(Stk_usb_com) / sizeof(StackType_t), NULL,                       		// 传递给任务的参数
        TD_PRI_HIGH, &Stk_usb_com[0], &thread_usb_com_tcb);
	if(thread_usb_com == NULL)
	{
		//Error_Handler();
        while(1);
	}
	
	
	test_sys_buf[9] = thread_usb_com;
	
	return 0;
}




/********************************(C)COPYRIGHT 2016 RSEStudio ****************************/
/*****************************************END OF FILE************************************/
